use std::io::Cursor;

use crate::byte::*;
use crate::workspace::WorkSpace;

use super::LiteralSectionHeader;
use super::error::LitResult;

#[derive(Debug)]
pub struct JumpTable {
    pub stream_compressed_size:[u16;4],
    pub stream_regenerated_size:[u32;4],
}

impl JumpTable {
    pub fn serialize_into<W:ByteWrite>(&self, writer:&mut ByteWriter<W>) -> LitResult<()> {
        for compressed_size in &self.stream_compressed_size[..3] {
            writer.write_from_u16(*compressed_size)?;
        }
        Ok(())
    }

    pub fn deserialize_from(header:&LiteralSectionHeader, total_streams_size:usize, raw_data:&[u8], _workspace:&mut WorkSpace) -> LitResult<Self> {
        assert_eq!(raw_data.len(), 6);
        let mut byte_reader = ByteReader::new(Cursor::new(raw_data));
        let stream1_size = byte_reader.read_to_u16()?;
        let stream2_size = byte_reader.read_to_u16()?;
        let stream3_size = byte_reader.read_to_u16()?;
        let stream4_size = total_streams_size as u16 - 6 
            - stream1_size
            - stream2_size
            - stream3_size;
        let stream_123_regenerated_size = (header.generated_size() + 3)/4;
        let stream4_regererated_size = header.generated_size() - 3 * stream_123_regenerated_size;
        Ok(Self {
            stream_compressed_size:[stream1_size, stream2_size, stream3_size, stream4_size],
            stream_regenerated_size:[
                stream_123_regenerated_size,
                stream_123_regenerated_size,
                stream_123_regenerated_size,
                stream4_regererated_size,
            ],
        })
    }

    pub fn stream_offset(&self) -> [core::ops::Range<usize>;4] {
        let stream1_offset = 0 as usize;
        let stream2_offset = stream1_offset + self.stream_compressed_size[0] as usize;
        let stream3_offset = stream1_offset + self.stream_compressed_size[1] as usize;
        let stream4_offset = stream1_offset + self.stream_compressed_size[2] as usize;
        let streams_offset = stream4_offset + self.stream_compressed_size[3] as usize;
        [
            stream1_offset..stream2_offset,
            stream2_offset..stream3_offset,
            stream3_offset..stream4_offset,
            stream4_offset..streams_offset,
        ]
    }
}